package com.hqq.leetcode.string;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * SwitchName 名称转换
 * 【Description】
 * 在C++头文件中可以使用include guard以避免头文件被重复include，譬如：
 * #ifndef MYHEADER_H_
 * #define MYHEADER_H_
 * ...
 * #endif
 * 现在我希望你编写一个程序，将类名按照某种规则转换为include guard所使用的宏。
 * 类名会包含namespace前缀，使用“.”作为分隔符。被分隔符分开的各个部分称之为组件，组件【只会包含大小写字母和数字，且不能以数字开头】。
 * 转换规则：
 * > 在开头和结尾都添加下划线；
 * > 将“.”转化为下划线；
 * > 根据下面的规则识别出组件中的单词，并使用下划线将单词进行分隔（具体参照输入输出样例）：
 * > 第一个大写字母与后面连续的小写字母一起识别为一个单词，如果不以大写字母开头，则直接将连续的小写字母识别为一个单词；
 * > 连续的大写字母一起识别为一个单词，但是如果最后一个大写字母后面跟着小写字母，则最后一个大写字母不包含在内；
 * > 连续的数字一起识别为一个单词
 * <p>
 * 【Input】多行字符串，每行是一个类名
 * a
 * my.ABC
 * simple.HelloService
 * MY.ASTParser12
 * 【Output】多行字符串，每行是一个转化后的include guard宏，与输入对应
 * _A_
 * _MY_ABC_
 * _SIMPLE_HELLO_SERVICE_
 * _MY_AST_PARSER_12_
 * <p>
 * Created by heqianqian on 2017/9/18.
 */
public class SwitchName {

    private static List<String> list = new ArrayList<>();

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            System.out.println(changeWord(line));
        }
    }

    private static String changeWord(String line) {
        if (line == null || line.length() == 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder("_");
        sb.append(line.charAt(0));
        char curr, prev;
        for (int i = 1; i < line.length(); i++) {
            curr = line.charAt(i);
            prev = line.charAt(i - 1);
            if ((isNumber(curr) && isLetter(prev)) || (isNumber(prev) && isLetter(curr))) {//数字和下划线情况
                sb.append("_").append(curr);
            } else if (isLower(curr) && isUpperLetter(prev)) {
                sb.insert(sb.length() - 1, "_");
                sb.append(curr);
            } else if (isUpperLetter(curr) && isLower(prev)) {
                sb.append("_").append(curr);
            } else {
                sb.append(curr);
            }
        }
        sb.append("_");
        return sb.toString().replaceAll("\\.", "_").replaceAll("__", "_").toUpperCase();
    }

    private static boolean isLower(char c) {
        return c >= 'a' && c <= 'z';
    }

    private static boolean isLetter(char c) {
        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
    }

    private static boolean isUpperLetter(char c) {
        return c >= 'A' && c <= 'Z';
    }

    private static boolean isNumber(char c) {
        return c >= '0' && c <= '9';
    }
}
